/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.dbdir.connections;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.logging.Level;
import org.dbdir.core.Logger;
import org.dbdir.Server;
import org.dbdir.core.AccessData;
import org.dbdir.core.Functions;
import org.dbdir.core.ProcessTCPCommand;

/**
 *
 * @author thotheolh
 */
public class TCPSession extends Thread {

//    private TCPServerSocket servsock = null;
    private Socket socks = null;
    private PrintWriter out = null;
    private BufferedReader in = null;
    private InputStreamReader instr = null;
    private Server servSess = null;
    private AccessData access = null;
    private String val_Username;
    private String val_Password;
    private String key_Username = "usr";
    private String key_Password = "pwd";
    private boolean isRun = true;
    private ProcessTCPCommand command;
    private AccessData data;
    private TCPSession session;
    private Functions funct;
    private boolean isLogin = false;
    private String[] nextrq;
    String inrq;
    private Logger logger;

    public TCPSession(Server server, Socket socket, AccessData data) {
        servSess = server;
        access = servSess.getAccessData();
        this.socks = socket;
        this.data = data;
        this.session = this;
        funct = servSess.getFunct();
        logger = server.getLog();
        command = new ProcessTCPCommand(data, session);
    }

    public void init() {
        try {
//            servsock = new TCPServerSocket(10999);
//            servsock.getSocksConnection();
//            if (socks == null) {
//                servsock = servSess.getServsock();
//                socks = servsock.getSocket();
//            }
            //output("servsock: " + servsock.toString() + "\n");
            output("sock: " + socks.toString() + "\n");
            out = new PrintWriter(socks.getOutputStream(), true);
            instr = new InputStreamReader(socks.getInputStream());
            in = new BufferedReader(instr);
            output("New TCP Session.\n");
            if (in.readLine().equals("dbdir"))//dbdir client's initial request
            {
                //output("Received 'dbdir'\n");
                out.println("ack");//dbdir server's acknowledgement
                while (true) {
                    if (isRun == true) {
                        inrq = in.readLine();
                        nextrq = inrq.split(" ");
                        if (nextrq[0].equals("addusr")) {
                            processMsg(inrq);
                        } else if (nextrq[0].equals("end")) {
                            processMsg("end");
                        } else if (nextrq[0].equals("login")) {
//                    do {
                            authenticate();
//                    } while (this.isLogin == false);
                        }
                    } else {
                        break;
                    }

                }
            }
        } catch (IOException ex) {
            output("Session client: "+socks.getInetAddress().getCanonicalHostName()+" dead...\n");
            logger.log(2, ex.getMessage()+" - Client dead");
        }catch (NullPointerException ex){
            output("Session client: "+socks.getInetAddress().getCanonicalHostName()+" dead...\n");
            logger.log(2, ex.getMessage()+" - Client dead");
        }
    }

    public void processMsg(String msg) {
        if (msg.equals("ping")) {
            out.println("pong");
        } else if (msg.equals("end")) {
            //end session
            out.println("ended");
            killSession();
            isRun = false;
        } else {
            command.processCmd(msg);
        }
    }

    public void output(String message) {
        servSess.output(message);
    }

    public void netout(String message) {
        out.println(message);
    }

    public void killSession() {
        try {
            String ipaddr = socks.getInetAddress().toString() + ":" + socks.getPort();
            //System.out.println("Killing Session..."); //verbose debug
            out.close();
            //System.out.println("Out closed..."); //verbose debug
            instr.close();
            //System.out.println("In Stream closed... "); //verbose debug
            in.close();
            //System.out.println("Buff Reader closed... "); //verbose debug
            socks.close();
            //System.out.println("Socks closed... "); //verbose debug
//            servsock.killConnection();
//            System.out.println("Server socks closed... "); //verbose debug
            output("Session: " + ipaddr + ", CLOSED !\n");
        } catch (IOException ex) {
            output("Session client: "+socks.getInetAddress().getCanonicalHostName()+" dead...\n");
            logger.log(2, ex.getMessage()+" - Client dead");
        }
    }

    @Override
    public void run() {
        init();
    }

    /**
     * @return the val_Username
     */
    public String getUsername() {
        return val_Username;
    }

    /**
     * @param val_Username the val_Username to set
     */
    public void setUsername(String val_Username) {
        this.val_Username = val_Username;
    }

    /**
     * @return the val_Password
     */
    public String getPassword() {
        return val_Password;
    }

    /**
     * @param val_Password the val_Password to set
     */
    public void setPassword(String val_Password) {
        this.val_Password = val_Password;
    }

    /**
     * @return the funct
     */
    public Functions getFunct() {
        return funct;
    }

    /**
     * @param funct the funct to set
     */
    public void setFunct(Functions funct) {
        this.funct = funct;
    }

    private void authenticate() {
//            inrq = in.readLine();
//            nextrq = inrq.split(" ");
//            if (nextrq[0].equals("login")) {
        //output("Received 'login'\n");
        String[] value1 = nextrq[1].split("=");
        String[] value2 = nextrq[2].split("=");
        if (value1[0].equals(this.key_Username)) {
            this.setUsername(value1[1]);
        } else if (value1[0].equals(this.key_Password)) {
            this.setPassword(value1[1]);
        }
        if (value2[0].equals(this.key_Username)) {
            this.setUsername(value2[1]);
        } else if (value2[0].equals(this.key_Password)) {
            this.setPassword(value2[1]);
        }
        if (this.getUsername() == null || this.getPassword() == null) {
            //out.println("auth-bad-cmd\n");
        } else {
            if (access.doUserLogin(getUsername(), getPassword()) == true) {
                out.println("auth-ok");
                this.isLogin = true;
                proceed();
            } else {
                out.println("auth-fail");
            }
        }
        //}

    }

    private void proceed() {
        while (true) {
            if (isRun == true) {
                try {
                    processMsg(in.readLine());
                } catch (IOException ex) {
                    output("Session client: "+socks.getInetAddress().getCanonicalHostName()+" dead...\n");
                    logger.log(2, ex.getMessage()+" - Client dead");
                }
            } else {
                break;
            }
        }
    }
}
